home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / uip / other / rcvtrip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-11  |  19.1 KB  |  830 lines

  1. /*
  2.  *     MULTI-CHANNEL MEMO DISTRIBUTION FACILITY  (MMDF)
  3.  *
  4.  *
  5.  *     Copyright (C) 1979,1980,1981  University of Delaware
  6.  *
  7.  *     Department of Electrical Engineering
  8.  *     University of Delaware
  9.  *     Newark, Delaware  19711
  10.  *
  11.  *     Phone:  (302) 738-1163
  12.  *
  13.  *     This program module was developed as part of the University
  14.  *     of Delaware's Multi-Channel Memo Distribution Facility (MMDF).
  15.  *
  16.  *     This module and its listings may be used freely by United States
  17.  *     federal, state, and local government agencies and by not-for-
  18.  *     profit institutions, after sending written notification to
  19.  *     Professor David J. Farber at the above address.
  20.  *
  21.  *     For-profit institutions may use this module, by arrangement.
  22.  *
  23.  *     Notification must include the name of the acquiring organization,
  24.  *     name and contact information for the person responsible for
  25.  *     maintaining the operating system, name and contact information
  26.  *     for the person responsible for maintaining this program, if other
  27.  *     than the operating system maintainer, and license information if
  28.  *     the program is to be run on a Western Electric Unix(TM) operating
  29.  *     system.
  30.  *
  31.  *     Documents describing systems using this module must cite its
  32.  *     source.
  33.  *
  34.  *     Development of this module was supported in part by the
  35.  *     University of Delaware and in part by contracts from the United
  36.  *     States Department of the Army Readiness and Materiel Command and
  37.  *     the General Systems Division of International Business Machines.
  38.  *
  39.  *     Portions of the MMDF system were built on software originally
  40.  *     developed by The Rand Corporation, under the sponsorship of the
  41.  *     Information Processing Techniques Office of the Defense Advanced
  42.  *     Research Projects Agency.
  43.  *
  44.  *     The above statements must be retained with all copies of this
  45.  *     program and may not be removed without the consent of the
  46.  *     University of Delaware.
  47.  *
  48.  *
  49.  *     version  -1    David H. Crocker    March  1979
  50.  *     version   0    David H. Crocker    April  1980
  51.  *     version   1    David H. Crocker    May    1981
  52.  *
  53.  */
  54.  
  55. /*
  56.  *                              RCVTRIP
  57.  *
  58.  *      Rcvtrip responds to incoming mail, recording who sent it, what the
  59.  *              subject was, when it came in, and if it was replied to.
  60.  *
  61.  *      The reply consists of some standard text, followed by any message
  62.  *              which the user wishes to specify.
  63.  *
  64.  *      Oct, 80     Bruce Whittaker         Initial coding and
  65.  *       - May, 81   (Whittake@Udel-EE)       maintenance
  66.  *
  67.  *    Sep  84 Julian Onions  jpo@nott.ac.uk
  68.  *        Total rewrite from the ground upwards, original ideas
  69.  *        kept, but now makes use of the mmdf library routines,
  70.  *        mmdf address parser and alias look up. This should
  71.  *        mean future changes will be easier to deal with. (?!)
  72.  *
  73.  *    Feb  85 Julian Onions  jpo@cs.nott.ac.uk
  74.  *        Rehacked to take into account weirdo addresses
  75.  *        + normali[zs]ed domain.s
  76.  *
  77.  *      Oct  87 Ian G. Batten  BattenIG@cs.bham.ac.uk
  78.  *              A backwards step!  Code included to allow for a file
  79.  *        called "~/.alter_egos" which contains user@site lines for 
  80.  *        all addresses to be considered to be "you".  This is needed
  81.  *        if you have multiple hosts forwarding their mail to you.
  82.  *
  83.  */
  84.  
  85. # include    "util.h"
  86. # include    "mmdf.h"
  87. # include    "ap.h"
  88. # include    "ch.h"
  89. # include    "hdr.h"
  90. # include    <pwd.h>
  91. # include    <stdio.h>
  92.  
  93. # define    ANIL        ((AP_ptr)0)
  94. # define    NILC        ((char *)0)
  95.  
  96. # define    NONFATAL    0    /* Nonfatal reports        */
  97. # define    FATAL        1    /* Fatal reports (exit)        */
  98. # define    TRACE        2    /* General info for debug    */
  99.  
  100. # define    SENT        0    /* Sent out a reply        */
  101. # define    UNSENT        1    /* No reply sent - just note    */
  102.  
  103. # define    REPLIED        '+'    /* A reply was sent        */
  104. # define    NOT_REPLIED    '-'    /* A reply wasn't sent        */
  105.  
  106. extern Llog    *logptr;
  107. extern int     ap_outtype;
  108.  
  109. extern char    *index ();
  110. extern char    *strcpy ();
  111. extern char    *strncpy ();
  112. extern char    *fgets ();
  113. extern char    *strcat ();
  114. extern char    *compress ();
  115. extern char    *ap_p2s ();
  116. extern char    *ap_s2p ();
  117. extern char    *getmailid();
  118. extern AP_ptr  ap_t2s ();
  119.  
  120. int    debug    =    FALSE;        /* output trace messages?       */
  121. int    found_1 =    FALSE;        /* true if message was sent to       */
  122.                     /* directly to recipient       */
  123. char    subj_field[ADDRSIZE];        /* contents of subject field       */
  124. char    username[20];            /* the users username           */
  125. char    logloc []    = "logfile";    /* where to log error conditions   */
  126. char    msg_note []    = "tripnote";    /* where to get reply message from */
  127. char    wholoc []    = "triplog";    /* where to note incoming messages */
  128. char    alter_egos []    = ".alter_egos"; /* where to get alternative names  */
  129. char    sigloc []    = ".signature"; /* where to find user's name       */
  130. char    tripsig []    = "MESSAGE AGENT";
  131.                     /* signature of the returned message*/
  132.  
  133. AP_ptr  resent_adr=    ANIL;        /* address tree for resent-from addr*/
  134. AP_ptr  rrepl_adr=    ANIL;        /* address " " resent-reply-to addr*/
  135. AP_ptr  rsndr_adr=    ANIL;        /* address " for resent-sender addr*/
  136. AP_ptr  from_adr=    ANIL;        /* address tree for from address   */
  137. AP_ptr  sndr_adr=    ANIL;        /*     - " -        sender       */
  138. AP_ptr  repl_adr=    ANIL;        /*     - " -        reply-to       */
  139.  
  140. char    *find_sig();
  141.  
  142. struct passwd    *getpwuid();
  143.  
  144. /*
  145.  *    This message is output before the users file message
  146.  */
  147. char    *text_message[] = {
  148.     "\tThis is an automatic reply.  Feel free to send additional\n",
  149.     "mail, as only this one notice will be generated.  The following\n",
  150.     "is a prerecorded message, sent for ", 0
  151. };
  152.  
  153. /*
  154.  *    This message is output if the users file is not readable or doesn't
  155.  *    exist. (This is where you can have some fun!)
  156.  */
  157. char    *error_txt[] = {
  158.     "\tIt appears that the person in question hasn't left a\n",
  159.     "message file, so the purpose of this message is unknown.\n",
  160.     "However it is assumed that as I, a daemon process,\n",
  161.     "have been called into existance that the person in question\n",
  162.     "is probably away for some time and won't be replying to your\n",
  163.     "message straight away.\n\nCheers,\n\tThe Mail System\n", 0
  164. };
  165.  
  166. typedef struct name_record
  167. {
  168.   char *name;
  169.   struct name_record *next_name_record;
  170. } NAME_RECORD;
  171.  
  172. NAME_RECORD *my_names;
  173.  
  174. main (argc, argv)
  175. int     argc;
  176. char  **argv;
  177. {
  178.     init (argc, argv);
  179.     parsemsg ();
  180.     doreplies ();
  181.     exit( RP_MECH );
  182. }
  183.  
  184. /*
  185.  *    Initialisation - get user, setup flags etc.
  186.  */
  187.  
  188. init (argc, argv)
  189. int     argc;
  190. char  **argv;
  191. {
  192.     FILE *names_file;
  193.     NAME_RECORD *temp;
  194.     char buffer[128];
  195.     register struct  passwd  *pwdptr;
  196.     int    realid, effecid;
  197.     char    *cp;
  198.  
  199.     ap_outtype = AP_822;        /* standardise on 822 */
  200.     argv ++;
  201.     if (argc > 1 && strcmp(*argv, "-d") == 0)
  202.     {
  203.         argv++;
  204.         argc--;
  205.         debug++;
  206.     }
  207.  
  208.     if( argc > 1 )  /* we have a command line sender address */
  209.         parse_addr(*argv, &sndr_adr);
  210.  
  211.     mmdf_init ("TRIP");
  212.  
  213.  
  214.   getwho (&realid, &effecid);
  215.   if((pwdptr = getpwuid (realid)) == (struct passwd *)0
  216.      || (cp = getmailid (pwdptr -> pw_name)) == NULL)
  217.     report( FATAL, "Can't Identify user %d", realid);
  218.   else
  219.     strcpy (username, cp);
  220.  
  221.   if ((names_file = fopen (alter_egos, "r")) != (FILE *) 0)
  222.     {
  223.       while ((fgets (buffer, sizeof buffer, names_file)) != NULL)
  224.     {
  225.       temp = (NAME_RECORD *) malloc (sizeof (NAME_RECORD));
  226.       
  227.       if (my_names == (NAME_RECORD *) 0)
  228.         {
  229.           my_names = temp;
  230.           temp->next_name_record = (NAME_RECORD *) 0;
  231.         }
  232.       else
  233.         {
  234.           temp->next_name_record = my_names;
  235.           my_names = temp;
  236.         }
  237.     
  238.       temp->name = (char *) malloc (strlen (buffer));
  239.       /* buffer + 1 for null, less 1 for CR */
  240.       buffer[strlen(buffer) -1] = '\0';         /* Zap the CR */
  241.       strcpy (temp->name, buffer);
  242.     }
  243.       fclose (names_file);
  244.     }
  245. }
  246.  
  247. /*
  248.  *    parse message - just a front end to the real parser
  249.  */
  250.  
  251. parsemsg()
  252. {
  253.     if( rp_isbad(hdr_fil(stdin)) )
  254.         report( FATAL, "parse of message failed");
  255. }
  256.  
  257. /*************** Routines to despatch messages ***************/
  258.  
  259. /*
  260.  *    Send replies to reply-to address if specified else
  261.  *        from and sender address.
  262.  */
  263.  
  264. doreplies()
  265. {
  266.     if( found_1 != TRUE )
  267.         report( FATAL, "Not sent directly to %s", username);
  268.  
  269.     if (from_adr == ANIL && sndr_adr == ANIL && resent_adr == ANIL
  270.                          && repl_adr == ANIL && rrepl_adr == ANIL
  271.                  && rsndr_adr == ANIL)
  272.         report( FATAL, "No parsable from or sender lines");
  273.  
  274. /*
  275.  *    If there were any reply-to lines, use those in preference.
  276.  */
  277.     if (rrepl_adr != ANIL)
  278.         replyto( rrepl_adr);
  279.     else if (resent_adr != ANIL) {
  280.         replyto( resent_adr );
  281.            if (rsndr_adr != ANIL)
  282.               replyto( rsndr_adr );
  283.              }
  284.     else if( repl_adr != ANIL )
  285.         replyto( repl_adr );
  286.     else    /*    send to both from && sender if they exist */
  287.     {
  288.         if (from_adr != ANIL)
  289.             replyto( from_adr );
  290.         if (sndr_adr != ANIL)
  291.             replyto( sndr_adr );
  292.     }
  293. }
  294.  
  295. /*
  296.  *    Actually do the work of sending the reply.
  297.  */
  298.  
  299. replyto( aptr )
  300. AP_ptr aptr;
  301. {
  302.     register char     *cp;
  303.     register char     **cpp;
  304.     AP_ptr  user, local, domain;
  305.     AP_ptr    norm;
  306.     char    *addr;
  307.     char    *ref;
  308.     char    *person;
  309.     char    buffer[ADDRSIZE];
  310.     FILE    *fp;
  311.  
  312. #ifdef    DEBUG
  313.     report( TRACE, "replyto()");
  314. #endif    DEBUG
  315.  
  316.     norm = ap_normalize( NILC, NILC, aptr, (Chan *)0);
  317.     ap_t2parts(norm, (AP_ptr *)0, &user, &local, &domain, (AP_ptr *)0);
  318.     ref = ap_p2s(ANIL, ANIL, local, domain, ANIL);
  319. #ifdef    DEBUG
  320.     report( TRACE, "normed addr = '%s'", ref);
  321. #endif    DEBUG
  322.  
  323.     if( user != ANIL)
  324.         person = user-> ap_obvalue;
  325.     else    person = NILC;
  326.  
  327.     if( checkuser( ref ) )
  328.     {
  329. #ifdef    DEBUG
  330.         report( TRACE, "Seen %s before", ref);
  331. #endif    DEBUG
  332.         noteuser( ref, UNSENT );
  333.         free( ref );
  334.         return;
  335.     }
  336.     if( ap_t2s(norm, &addr) == (AP_ptr)NOTOK)
  337.     {
  338.         report( NONFATAL, "Parse error for %s", addr);
  339.         noteuser( ref, UNSENT);
  340.         free( ref );
  341.         return;
  342.     }
  343.     buffer[0] = '\0';
  344.     if( ! prefix("re:", subj_field) )
  345.         strcpy( buffer, "Re: ");
  346.  
  347.     strcat( buffer, subj_field);
  348.  
  349. #ifdef    DEBUG
  350.     report(TRACE, "ml_1adr(NO, NO, '%s' %s, %s)",
  351.             tripsig, buffer, addr);
  352. #endif    DEBUG
  353.  
  354.     ml_1adr( NO, NO, tripsig, buffer, addr);
  355.  
  356.     if( person != NILC)
  357.     {
  358.         compress(person, person);
  359.         sprintf( buffer, "\nDear %s,\n", person);
  360. #ifdef    DEBUG
  361.         report( TRACE, "1st line %s", buffer);
  362. #endif    DEBUG
  363.         ml_txt( buffer );
  364.     }
  365.  
  366. #ifdef    DEBUG
  367.     report( TRACE, "start builtin message");
  368. #endif    DEBUG
  369.     for( cpp = text_message; *cpp != NILC ; cpp++)
  370.         ml_txt( *cpp );
  371.     if(( cp = find_sig()) != NILC)
  372.         ml_txt( cp );
  373.     else    ml_txt( username );
  374.     ml_txt("\n\n\n");
  375.  
  376.     if( (fp = fopen( msg_note, "r")) != (FILE *)0)
  377.     {
  378. #ifdef    DEBUG
  379.         report( TRACE, "processing file %s", msg_note);
  380. #endif    DEBUG
  381.         ml_file(fp);
  382.         fclose(fp);
  383.     }
  384.     else
  385.     {
  386. #ifdef    DEBUG
  387.         report( TRACE, "Sending built in error message");
  388. #endif    DEBUG
  389.         for( cpp = error_txt; *cpp != NILC; cpp++)
  390.             ml_txt(*cpp);
  391.     }
  392. #ifdef    DEBUG
  393.     report( TRACE, "ml_end(OK)");
  394. #endif    DEBUG
  395.     if( ml_end(OK) == OK)
  396.         noteuser(ref, SENT);
  397.     else    noteuser(ref, UNSENT);
  398.     free( ref );
  399.     free( addr );
  400. }
  401.  
  402. /*************** Routines to pick apart the message ***************/
  403.  
  404. /*
  405.  *    The actual picking out of headers
  406.  */
  407.  
  408. hdr_fil (msg)
  409. FILE * msg;            /* The message file             */
  410. {
  411.     char    line[LINESIZE];    /* temp buffer             */
  412.     char    name[LINESIZE];    /* Name of header field         */
  413.     char    contents[LINESIZE];/* Contents of header field     */
  414.     int     len;
  415.  
  416. #ifdef    DEBUG
  417.     report (TRACE, "hdr_fil()");
  418. #endif    DEBUG
  419.     if (msg == (FILE *) NULL)
  420.     {
  421.         report( FATAL, "NULL file pointer");
  422.         return (RP_NO); /* not much point doing anything else */
  423.     }
  424. /* process the file    */
  425.  
  426.     FOREVER
  427.     {
  428.         if ((len = gcread (msg, line, LINESIZE, "\n\377")) < 1)
  429.         {
  430.             report( NONFATAL, "read error on message");
  431.             return(RP_NO);  /* skip and go home */
  432.         }
  433.         line[len] = '\0';
  434.  
  435.         switch (hdr_parse (line, name, contents))
  436.         {
  437.         case HDR_NAM: /* No name so contine through header */
  438.             continue;
  439.  
  440.         case HDR_EOH: /* End of header - lets go home */
  441.             return(RP_OK);
  442.  
  443.         case HDR_NEW:
  444.         case HDR_MOR: /* We have a valid field        */
  445.             if (lexequ (name, "to") ||
  446.                 lexequ(name, "cc") ||
  447.                 lexequ(name, "resent-to") ||
  448.                 lexequ(name, "resent-cc") )
  449.             {
  450.                 find_user(contents);
  451.                 break;
  452.             }
  453.             else    if (lexequ (name, "resent-reply-to"))
  454.             {
  455.                 parse_addr(contents, &rrepl_adr);
  456.                 break;
  457.             }
  458.             else    if (lexequ (name, "resent-sender"))
  459.             {
  460.                 parse_addr(contents, &rsndr_adr);
  461.                 break;
  462.             }
  463.             else    if (lexequ (name, "resent-from"))
  464.             {
  465.                 parse_addr(contents, &resent_adr);
  466.                 break;
  467.             }
  468.             else    if (lexequ (name, "from"))
  469.             {
  470.                 parse_addr(contents, &from_adr);
  471.                 break;
  472.             }
  473.             else    if (lexequ (name, "reply-to"))
  474.             {
  475.                 parse_addr(contents, &repl_adr);
  476.                 break;
  477.             }
  478.             else    if (lexequ (name, "sender"))
  479.             {
  480.                 parse_addr(contents, &sndr_adr);
  481.                 break;
  482.             }
  483.             else    if (lexequ (name, "subject"))
  484.             {
  485.                 strncpy(subj_field, contents, ADDRSIZE-1);
  486.                 break;
  487.             }
  488.             else
  489.                 continue;
  490.         }
  491.     }
  492. }
  493.  
  494. /*
  495.  *    The real parser
  496.  */
  497.  
  498. LOCFUN
  499. hdr_parse (src, name, contents)    /* parse one header line         */
  500. register char  *src;        /* a line of header text         */
  501. char   *name,            /* where to put field's name         */
  502.        *contents;        /* where to put field's contents     */
  503. {
  504.     extern char    *compress ();
  505.     char        linetype;
  506.     register char  *dest;
  507.  
  508. #ifdef    DEBUG
  509.     report (TRACE, "hdr_parse('%s')", src);
  510. #endif    DEBUG
  511.  
  512.     if (isspace (*src))
  513.     {            /* continuation text             */
  514. #ifdef    DEBUG
  515.         report( TRACE, "hrd_parse -> cmpnt more");
  516. #endif    DEBUG
  517.         if (*src == '\n')
  518.             return (HDR_EOH);
  519.         linetype = HDR_MOR;
  520.     }
  521.     else
  522.     {            /* copy the name            */
  523.         linetype = HDR_NEW;
  524.         for (dest = name; *dest = *src++; dest++)
  525.         {
  526.             if (*dest == ':')
  527.                 break;        /* end of the name    */
  528.             if (*dest == '\n')
  529.             {    /* oops, end of the line        */
  530.                 *dest = '\0';
  531.                 return (HDR_NAM);
  532.             }
  533.         }
  534.         *dest = '\0';
  535.         compress (name, name);/* strip extra & trailing spaces     */
  536. #ifdef    DEBUG
  537.         report (TRACE, "hdr_parse -> cmpnt name '%s'", name);
  538. #endif    DEBUG
  539.     }
  540.  
  541.     for (dest = contents; isspace (*src);)
  542.         if (*src++ == '\n')/* skip leading white space         */
  543.         {        /* unfulfilled promise, no contents     */
  544.             *dest = '\0';
  545.             return ((linetype == HDR_MOR) ? HDR_EOH : linetype);
  546.         }        /* hack to fix up illegal spaces     */
  547.  
  548.     while ((*dest = *src) != '\n' && *src != 0)
  549.         src++, dest++;    /* copy contents and then, backup     */
  550.     while (isspace (*--dest));/*   to eliminate trailing spaces     */
  551.     *++dest = '\0';
  552.  
  553.     return (linetype);
  554. }
  555.  
  556. /*************** Parsing of addresses got from message ***************/
  557.  
  558. /*
  559.  *    See if user is in this field. parse address first and
  560.  *        compare mbox's.
  561.  */
  562.  
  563. find_user(str)
  564. char *str;
  565. {
  566.     AP_ptr tree, local, domain;
  567.     char *p;
  568.     NAME_RECORD *temp;
  569.  
  570. #ifdef    DEBUG
  571.     report(TRACE, "find_user('%s')", str);
  572. #endif    DEBUG
  573.     if( found_1 == TRUE)
  574.     {
  575. #ifdef    DEBUG
  576.         report(TRACE, "find_user() name already found\n");
  577. #endif    DEBUG
  578.         return;
  579.     }
  580.  
  581.     while( (str = ap_s2p(str, &tree, (AP_ptr *)0, (AP_ptr *)0, &local,
  582.         &domain, (AP_ptr *)0) ) != (char *)DONE
  583.         && str != (char *) NOTOK )
  584.     {
  585.       if (my_names == (NAME_RECORD *) 0) /* No alter-ego file found */
  586.         {
  587.           p = ap_p2s( ANIL, ANIL, local, ANIL, ANIL);
  588. #ifdef    DEBUG
  589.           report( TRACE, "find_user() -> found mbox %s", p);
  590. #endif    DEBUG
  591.           if( lexequ(p, username) )
  592.         found_1 = TRUE;
  593.           else    found_1 = alias(p, username) ? TRUE: FALSE;
  594.         }
  595.       else
  596.         {
  597.           p = ap_p2s (ANIL, ANIL, local, domain, ANIL);
  598.           for (temp = my_names; temp != (NAME_RECORD *) 0; 
  599.            temp = temp->next_name_record)
  600.         {
  601. #ifdef DEBUG
  602.           report (TRACE, "find_user (): Testing %s vs. %s\n", p, temp->name);
  603. #endif DEBUG
  604.  
  605.           if (lexequ (p, temp->name))
  606.             found_1 = TRUE;
  607.         }
  608.         }
  609.           
  610.         free(p);
  611.         ap_sqdelete(tree, ANIL);
  612.         ap_free(tree);
  613.         if( found_1 == TRUE )
  614.             return;
  615.     }
  616. }
  617. /*
  618.  *    Attempt to parse a field into an address tree for later use.
  619.  */
  620.  
  621. parse_addr( str, aptr)
  622. char    *str;
  623. AP_ptr  *aptr;
  624. {
  625.  
  626. #ifdef    DEBUG
  627.     report( TRACE, "parse_addr('%s')", str);
  628. #endif    DEBUG
  629.  
  630.     if( *aptr != ANIL)
  631.     {
  632. #ifdef    DEBUG
  633.         report( TRACE, "field '%s' rejected, already seen one");
  634. #endif    DEBUG
  635.         return;
  636.     }
  637.  
  638.     if( (*aptr = ap_s2tree(str) ) == (AP_ptr)NOTOK)
  639.         report( NONFATAL, "Can't parse address '%s'", str);
  640. }
  641.  
  642. /*************** User Data Base Routines ***************/
  643.  
  644. /*
  645.  *    Note the fact we did/didnot reply to a given person
  646.  *    and include the subject line for good measure.
  647.  */
  648.  
  649. noteuser(addr, mode)
  650. char    *addr;
  651. int    mode;
  652. {
  653.     FILE    *fp;
  654.     time_t  now;
  655.     char    *ctime();
  656.  
  657. #ifdef    DEBUG
  658.     report( TRACE, "noteuser(%s,%d)", addr, mode);
  659. #endif    DEBUG
  660.  
  661.     time(&now);
  662.  
  663.     if( (fp = fopen(wholoc, "a")) != NULL)
  664.     {
  665.         chmod(wholoc, 0600);
  666.         fprintf( fp, "%c %-30s %19.19s >> %.20s\n", mode == SENT? REPLIED: NOT_REPLIED,
  667.             addr, ctime(&now), subj_field);
  668.         fclose(fp);
  669.     }
  670. }
  671. /*
  672.  *    Have we replied to this person before?
  673.  */
  674. checkuser( addr )
  675. char *addr;
  676. {
  677.     FILE    *fp;
  678.     char    buffer[LINESIZE];
  679.     char    compaddr[LINESIZE];
  680.  
  681.     if((fp = fopen(wholoc, "r")) == NULL)
  682.         return FALSE;
  683.     while( fgets( buffer, sizeof buffer, fp) != NULL)
  684.     {
  685.         if(buffer[0] == NOT_REPLIED )
  686.             continue;
  687.         getaddress(buffer, compaddr);
  688. #ifdef    DEBUG
  689.         report( TRACE, "checkuser, = '%s' & '%s'?", compaddr, addr);
  690. #endif    DEBUG
  691.         if( lexequ(compaddr, addr) )
  692.         {
  693.             fclose(fp);
  694.             return TRUE;
  695.         }
  696.     }
  697.     return FALSE;
  698. }
  699.  
  700. /*************** Alias Lookup ***************/
  701.  
  702. /*
  703.  *    Saunter thru the alias table looking for aliases
  704.  *    This only looks for single pass aliases, for two reasons
  705.  *    1)    Its more work than I can be bothered to do now.
  706.  *    2)    If its more than a simple alias substitution, then
  707.  *        its probably part of an address list or something
  708.  *        similarly complicated, in which case its probably
  709.  *        better to keep quite about it.
  710.  */
  711.  
  712. alias(str, uname)
  713. char    *str;
  714. char    *uname;
  715. {
  716.     char    aliasval[ADDRSIZE];
  717.     register char    *p;
  718.  
  719. #ifdef    DEBUG
  720.     report( TRACE, "alias(%s, %s)", str, uname);
  721. #endif    DEBUG
  722.     if (aliasfetch(TRUE, str, aliasval, 0) != OK)
  723.         return FALSE;
  724.     p = aliasval;
  725.     if( *p == '~')  p++;        /* strip off leading ~ */
  726.  
  727.     return lexequ(p, uname);
  728. }
  729.  
  730. /*************** Some Utility Routines ***************/
  731.  
  732.  
  733. /*
  734.  *    Dig out a signature for the user
  735.  */
  736.  
  737. char *find_sig()
  738. {
  739.     FILE *fp;
  740.     static char buf[ADDRSIZE];
  741.     static int  been_here = FALSE;
  742.     char *p;
  743.  
  744. #ifdef    DEBUG
  745.     report( TRACE, "find_sig()");
  746. #endif    DEBUG
  747.  
  748.     if( been_here == TRUE )  /* cuts off at least 1/4 micro-second */
  749.         return buf;
  750.  
  751.     if((fp = fopen(sigloc, "r")) == NULL)
  752.         return NILC;
  753.     if( fgets(buf, sizeof(buf), fp) == NILC)
  754.     {
  755.         fclose(fp);
  756.         return NILC;
  757.     }
  758.     if( (p = index(buf, '\n')) != NILC)
  759.         *p = '\0';
  760.     fclose(fp);
  761.     return buf;
  762. }
  763.  
  764. getaddress(source, dest)
  765. char *source, *dest;
  766. {
  767.     register char *p;
  768.     int    depth = 0;
  769.  
  770.     p = source + 2;        /* skip over reply indicator */
  771.     while(*p)
  772.     {
  773.         switch( *p )
  774.         {
  775.             case '"':    /* in quoted part ? */
  776.                 depth = !depth;
  777.                 break;
  778.             case ' ':
  779.             case '\t':
  780.                 if( depth == 0)
  781.                 {
  782.                     *dest = '\0';
  783.                     return;
  784.                 }
  785.                 break;
  786.             case '\\':    /* gobble up next char */
  787.                 *dest++ = *p++;
  788.                 break;
  789.         }
  790.         *dest++ = *p++;
  791.     }
  792.     *dest = '\0';
  793. }
  794.  
  795. /*VARARGS2*/
  796. report( mode, fmt, a1, a2, a3, a4)
  797. int mode;
  798. char *fmt, *a1, *a2, *a3, *a4;
  799. {
  800.     static FILE *log;
  801.  
  802.     if( debug == FALSE && mode == TRACE)
  803.         return;
  804.     if( log == NULL && access(logloc, 0) != -1)
  805.     {
  806.         log = fopen(logloc, "a");
  807.         chmod(logloc, 0600);        /* keep things private */
  808.     }
  809.     if( debug == TRUE )
  810.     {
  811.         fprintf( stderr,"%s\t", mode == TRACE?"TRACE":
  812.             (mode == FATAL?"FATAL":"!FATAL"));
  813.         fprintf( stderr, fmt, a1, a2, a3, a4);
  814.         putc('\n', stderr);
  815.         fflush( stderr);
  816.     }
  817.     if( log != NULL)
  818.     {
  819.         fprintf( log, "%s\t", mode == TRACE?"TRACE":
  820.             (mode == FATAL?"FATAL":"!FATAL"));
  821.         fprintf( log, fmt, a1, a2, a3, a4);
  822.         putc('\n', log);
  823.         fflush( log );
  824.     }
  825.     else if(mode != TRACE)
  826.         ll_log( logptr, LLOGTMP, fmt, a1, a2, a3, a4);
  827.     if( mode == FATAL)
  828.         exit(RP_MECH);        /* die a horrible death */
  829. }
  830.